package com.mindata.blockchain.core.controller;

import com.google.common.collect.Maps;
import com.mindata.blockchain.block.Block;
import com.mindata.blockchain.block.Instruction;
import com.mindata.blockchain.block.Operation;
import com.mindata.blockchain.common.CommonUtil;
import com.mindata.blockchain.common.FastJsonUtil;
import com.mindata.blockchain.common.HttpClientHelper;
import com.mindata.blockchain.core.bean.BaseData;
import com.mindata.blockchain.core.bean.ResultGenerator;
import com.mindata.blockchain.core.manager.OrderManager;
import com.mindata.blockchain.core.manager.OrderTrackManager;
import com.mindata.blockchain.core.manager.PayManager;
import com.mindata.blockchain.core.manager.TicketManager;
import com.mindata.blockchain.core.model.*;
import com.mindata.blockchain.core.model.convert.OrderInfoModel;
import com.mindata.blockchain.core.requestbody.BlockRequestBody;
import com.mindata.blockchain.core.requestbody.InstructionBody;
import com.mindata.blockchain.core.service.BlockService;
import com.mindata.blockchain.core.service.InstructionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.sql.Date;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 王鹏
 */
@Api(tags = "订单", description = "订单相关业务接口")
@RestController
@RequestMapping("/order")
public class OrderController {

    @Resource
    private InstructionService instructionService;

    @Resource
    private BlockService blockService;


    @Resource
    private TicketManager ticketManager;

    @Resource
    private OrderManager orderManager;

    @Resource
    private PayManager payManager;

    @Resource
    private TicketController ticketController;

    @Resource
    private OrderTrackManager orderTrackManager;

    public String sceneryUrl;

    @Value("${publicKey:A8WLqHTjcT/FQ2IWhIePNShUEcdCzu5dG+XrQU8OMu54}")
    private String publicKey;
    @Value("${privateKey:yScdp6fNgUU+cRUTygvJG4EBhDKmOMRrK4XJ9mKVQJ8=}")
    private String privateKey;


    @ApiOperation(value = "购票接口---前端使用", notes = "购票接口", httpMethod = "GET", response = BaseData.class)
    @RequestMapping("/getAllOrder")
    public BaseData getAllOrder() {
        List<OrderEntity> allEntity = orderManager.getAllEntity();
        return ResultGenerator.genSuccessResult(allEntity);
    }

    @RequestMapping("/getAllOrderDetail")
    @ApiOperation(value = "获取所有订单详情", notes = "获取所有订单详情", httpMethod = "GET", response = BaseData.class)
    public BaseData getAllOrderDetail() {
        List<OrderTrackEntity> all = orderTrackManager.findAll();
        return ResultGenerator.genSuccessResult(all);
    }


    @RequestMapping("/createOrder")
    @ApiOperation(value = "购票接口---前端使用", notes = "购票接口", httpMethod = "GET", response = BaseData.class)
    public BaseData buyTicket(@ApiParam(name = "idCard", value = "身份唯一标识", required = true) @RequestParam("idCard") String idCard) throws Exception {

        BlockRequestBody blockRequestBody = new BlockRequestBody();
        blockRequestBody.setPublicKey(publicKey);
        com.mindata.blockchain.block.BlockBody blockBody = new com.mindata.blockchain.block.BlockBody();

        List<Instruction> instructionList = Lists.newArrayList();
        // 修改票状态
        InstructionBody ticketInstructionBody = new InstructionBody();
        ticketInstructionBody.setOperation(Operation.UPDATE);
        ticketInstructionBody.setTable("ticket");

        TicketEntity ticketEntity = ticketManager.findAll(0).get(0);

        Map<String, String> ticketMap = Maps.newHashMapWithExpectedSize(3);
        ticketMap.put("sceneryName", ticketEntity.getSceneryName());
        ticketMap.put("ticketName", ticketEntity.getTicketName());
        ticketMap.put("status", "1");
        ticketInstructionBody.setInstructionId(ticketEntity.getMessageId());
        ticketInstructionBody.setJson(FastJsonUtil.toJSONString(ticketMap));
        ticketInstructionBody.setPublicKey(publicKey);
        ticketInstructionBody.setPrivateKey(privateKey);
        Instruction ticketInstruction = instructionService.build(ticketInstructionBody);

        // 创建订单
        InstructionBody orderInstructionBody = new InstructionBody();
        orderInstructionBody.setOperation(Operation.ADD);
        orderInstructionBody.setTable("order_main");

        Map<String,Object> orderMap = Maps.newHashMapWithExpectedSize(4);
        orderMap.put("ticketId",ticketEntity.getMessageId());
        orderMap.put("idCard",idCard);
        orderMap.put("status",0);
        orderMap.put("sceneryName",ticketEntity.getSceneryName());
        orderInstructionBody.setJson(FastJsonUtil.toJSONString(orderMap));
        orderInstructionBody.setPublicKey(publicKey);
        orderInstructionBody.setPrivateKey(privateKey);
        Instruction orderInstruction = instructionService.build(orderInstructionBody);
        // 注意顺序
        instructionList.add(orderInstruction);
        instructionList.add(ticketInstruction);


        blockBody.setInstructions(instructionList);
        blockRequestBody.setBlockBody(blockBody);

        Block block = blockService.addBlock(blockRequestBody);


        String orderId = orderInstruction.getInstructionId();
        Map<String, Object> respMap = Maps.newHashMapWithExpectedSize(3);
        respMap.put("orderId", orderId);

        OrderTrackEntity orderTrack = new OrderTrackEntity();
        orderTrack.setOrderId(orderId);
        orderTrack.setOrderStatus(0);
        orderTrack.setCreateTime(CommonUtil.getNow());
        orderTrackManager.insertOrderTrack(orderTrack);
        return ResultGenerator.genSuccessResult(respMap);
    }

    @RequestMapping("/pay")
    @ApiOperation(value = "支付接口---前端使用", notes = "支付接口", httpMethod = "GET", response = BaseData.class)
    public BaseData pay(@ApiParam(name = "orderId") @RequestParam("orderId") String orderId) throws Exception {

        OrderEntity orderEntity = orderManager.findByOrderId(orderId);

        BlockRequestBody blockRequestBody = new BlockRequestBody();
        blockRequestBody.setPublicKey(publicKey);
        com.mindata.blockchain.block.BlockBody blockBody = new com.mindata.blockchain.block.BlockBody();

        List<Instruction> instructionList = Lists.newArrayList();
        // 修改票状态
        InstructionBody ticketInstructionBody = new InstructionBody();
        ticketInstructionBody.setOperation(Operation.ADD);
        ticketInstructionBody.setTable("pay");


        Map<String, String> payMap = Maps.newHashMapWithExpectedSize(3);
        payMap.put("orderId", orderId);
        ticketInstructionBody.setJson(FastJsonUtil.toJSONString(payMap));
        ticketInstructionBody.setPublicKey(publicKey);
        ticketInstructionBody.setPrivateKey(privateKey);
        Instruction payInstruction = instructionService.build(ticketInstructionBody);
        instructionList.add(payInstruction);

        InstructionBody orderInstructionBody = new InstructionBody();
        orderInstructionBody.setOperation(Operation.UPDATE);
        orderInstructionBody.setTable("order_main");

        Map<String,Object> orderMap = Maps.newHashMapWithExpectedSize(4);
        orderMap.put("status",1);
        orderInstructionBody.setInstructionId(orderId);
        orderInstructionBody.setJson(FastJsonUtil.toJSONString(orderMap));
        orderInstructionBody.setPublicKey(publicKey);
        orderInstructionBody.setPrivateKey(privateKey);
        Instruction orderInstruction = instructionService.build(orderInstructionBody);
        instructionList.add(orderInstruction);


        blockBody.setInstructions(instructionList);
        blockRequestBody.setBlockBody(blockBody);
        Block block = blockService.addBlock(blockRequestBody);


        OrderTrackEntity orderTrack = new OrderTrackEntity();
        orderTrack.setOrderId(orderId);
        orderTrack.setOrderStatus(1);
        orderTrack.setCreateTime(CommonUtil.getNow());
        orderTrackManager.insertOrderTrack(orderTrack);

        CompletableFuture.runAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            try {

                String response = HttpClientHelper.GetString(sceneryUrl + "/ticket/sendTicket?ticketId=" + orderEntity.getTicketId());
                System.out.println(response);

//                ticketController.sendTicket(orderEntity.getTicketId());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });


        return ResultGenerator.genSuccessResult("支付成功");
    }


    @RequestMapping("/getPayList")
    @ApiOperation(value = "获取支付信息", notes = "支付列表", httpMethod = "GET", response = BaseData.class)
    public BaseData getPayList() {
        List<PayEntity> all = payManager.findAll();
        return ResultGenerator.genSuccessResult(all);
    }


    @RequestMapping("/getOrderDetail")
    @ApiOperation(value = "获取订单详情----前端使用", notes = "订单详情", httpMethod = "GET", response = BaseData.class)
    public BaseData getOrderDetail(@ApiParam(name = "orderId") @RequestParam("orderId") String orderId) {
        List<OrderTrackEntity> list = orderTrackManager.findByOrderId(orderId);

        OrderEntity order = orderManager.findByOrderId(orderId);
        String ticketId = order.getTicketId();
        TicketEntity ticket = ticketManager.findByTicketId(ticketId);


        Map<String, Object> resp = new HashMap<>();
        List<Map<String, Object>> orderLogList = new ArrayList<>();
        int index = 0;
        for (OrderTrackEntity orderTrack : list) {
            Map<String, Object> orderLog = new HashMap<>();
            orderLog.put("time", DateFormatUtils.format(orderTrack.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            Pair<String, String> orderStatusDetail = getOrderStatusDetail(orderTrack.getOrderStatus());
            orderLog.put("desc", orderStatusDetail.getRight());
            orderLog.put("statusDesc", orderStatusDetail.getLeft());
            orderLog.put("status", orderTrack.getOrderStatus());
            orderLogList.add(orderLog);
            index++;
        }


        resp.put("logList", orderLogList);
        Map<String, Object> ticketMap = new HashMap<>();
        ticketMap.put("ticketName", ticket.getTicketName());
        ticketMap.put("sceneryName", ticket.getSceneryName());
        ticketMap.put("price", ticket.getPrice());
        resp.put("ticketInfo", ticketMap);
        resp.put("showQR", index == 3 );
        resp.put("orderStatus", index - 1);
        return ResultGenerator.genSuccessResult(resp);
    }


    @RequestMapping("/refundOrder")
    @ApiOperation(value = "退款----前端使用", notes = "退款", httpMethod = "GET", response = BaseData.class)
    public BaseData refundOrder(@ApiParam(name = "orderId") @RequestParam("orderId") String orderId) {
        OrderTrackEntity orderTrack = new OrderTrackEntity();
        orderTrack.setOrderId(orderId);
        orderTrack.setOrderStatus(3);
        orderTrack.setCreateTime(CommonUtil.getNow());
        orderTrackManager.insertOrderTrack(orderTrack);
        return ResultGenerator.genSuccessResult("成功");
    }

    Pair<String, String> getOrderStatusDetail(Integer status) {
        if (status == 0) {
            return Pair.of("【订单创建】", "新建订单待支付");
        } else if (status == 1) {
            return Pair.of("【订单支付成功】", "订单支付成功，正在全力为您出票中，请稍等");
        } else if (status == 2) {
            return Pair.of("【出票成功】", "已为您出票成功，请凭有效证件入园");
        } else if (status == 3) {
            return Pair.of("【已退款】", "已退款");
        } else {
            return Pair.of("未知", "未知");
        }
    }

    @RequestMapping("/setSceneryUrl")
    public String setSceneryUrl(@RequestParam("url") String url) {
        this.sceneryUrl = url;
        return "success";
    }


    @RequestMapping("/getAllTickets")
    @ApiOperation(value = "景区门票列表", notes = "景区门票列表", httpMethod = "GET", response = BaseData.class)
    public BaseData getAllTickets() {
        List<TicketInfoModel> response = new ArrayList<>();
        List<TicketEntity> all = ticketManager.findAllTicket();
        if (!CollectionUtils.isEmpty(all)) {
            Map<String, List<TicketEntity>> map = all.stream().collect(Collectors.groupingBy(TicketEntity::getTicketName));
            for (Map.Entry<String, List<TicketEntity>> stringListEntry : map.entrySet()) {
                if (!CollectionUtils.isEmpty(stringListEntry.getValue())) {
                    TicketInfoModel ticketInfoModel = new TicketInfoModel();
                    ticketInfoModel.setSceneryName(stringListEntry.getValue().get(0).getSceneryName());
                    ticketInfoModel.setTicketName(stringListEntry.getValue().get(0).getTicketName());
                    ticketInfoModel.setPrice(stringListEntry.getValue().get(0).getPrice());
                    ticketInfoModel.setInventoryNum(stringListEntry.getValue().stream().filter(s -> s.getStatus().equals(0)).count());
                    response.add(ticketInfoModel);
                }
            }
        }
        return ResultGenerator.genSuccessResult(response);
    }

    @RequestMapping("/getAllOrders")
    @ApiOperation(value = "订单列表", notes = "订单列表", httpMethod = "GET", response = BaseData.class)
    public BaseData getAllOrders(@ApiParam(name = "sceneryName") @RequestParam("sceneryName") String sceneryName) {
        List<OrderInfoModel> response = new ArrayList<>();
        List<OrderEntity> allOrder = new ArrayList<>();
        if (StringUtils.isNotEmpty(sceneryName)) {
            allOrder = orderManager.getOrderBySceneryName(sceneryName);
        } else {
            allOrder = orderManager.getAllEntity();
        }
        if (!CollectionUtils.isEmpty(allOrder)) {
            for (OrderEntity order : allOrder) {
                TicketEntity ticket = ticketManager.findByTicketId(order.getTicketId());
                if (ticket != null) {
                    OrderInfoModel orderInfo = new OrderInfoModel();
                    orderInfo.setOrderId(order.getOrderId());
                    orderInfo.setIdCard(order.getIdCard());
                    orderInfo.setStatus(order.getStatus());
                    orderInfo.setTicketName(ticket.getTicketName());
                    orderInfo.setSceneryName(ticket.getSceneryName());
                    orderInfo.setPrice(ticket.getPrice());
                    switch (order.getStatus()) {
                        case 0:
                            orderInfo.setStatusDesc("订单创建");
                            break;
                        case 1:
                            orderInfo.setStatusDesc("已支付");
                            break;
                        case 2:
                            orderInfo.setStatusDesc("已出票");
                            break;
                        case 3:
                            orderInfo.setStatusDesc("已退款");
                            break;
                        default:
                            orderInfo.setStatusDesc("未知");
                            break;
                    }
                    response.add(orderInfo);
                }
            }
        }
        return ResultGenerator.genSuccessResult(response);
    }

}
